import { Injectable } from '@angular/core';
import {Hero} from './hero';
// import {HEROES} from './mock-heroes';
import {Observable,of} from 'rxjs';
import {catchError,map,tap} from 'rxjs/operators'
import {MessageService} from './message.service';

import {HttpClient,HttpHeaders} from '@angular/common/http';
const httpOptions ={
  headers: new HttpHeaders({ 'Content-Type': 'application/json' })
}
@Injectable({
  providedIn: 'root'
})

export class HeroService {
  private heroesUrl ='api/heroes';
 
  constructor(private http:HttpClient, private messageService:MessageService) {

   }
  private log(message:string){
    this.messageService.add(`HeroService: ${message}`)
  }
  // operation :string='';
  private handleError<T>(operation='operation',result?:T){
   return (error:any):Observable<T>=>{
     console.error(error)
     this.log(`${operation} failed :${error.message}`)
    return of(result as T)
   }
  }
   /** GET heroes from the server */
  getHeroes():Observable<Hero[]>{
    // this.messageService.add('HeroService: fetched heroes')
    // return of(HEROES);
    return this.http.get<Hero[]>(this.heroesUrl)
    .pipe(
      tap(_=>this.log('fecthed heroes')),
        catchError(this.handleError<Hero[]>('getHeroes',[]))
    )
  }
  getHero(id:number):Observable<Hero>{
    // this.messageService.add(`HeroService: fetched heroes id=${id}`)
    const url = `${this.heroesUrl}/${id}`
    // return of(HEROES.find(hero=>hero.id===id))
    return this.http.get<Hero>(url).pipe(
        tap(_=>this.log(`feched heroes id=${id}`)),
        catchError(this.handleError<Hero>(`getHero id=${id}`))
    )
  }
  updateHero(hero:Hero):Observable<any>{
      return this.http.put(this.heroesUrl,hero,httpOptions)
      .pipe(
        tap(_=>this.log(`update hero id=${hero.id}`)),
        catchError(this.handleError<any>('updateHero'))
      )
  }
  addHero(hero:Hero):Observable<Hero>{
    return this.http.post<Hero>(this.heroesUrl,hero,httpOptions)
    .pipe(
      tap((newHero:Hero)=>this.log(`added hero w/ id=${newHero.id}`)),
      catchError(this.handleError<Hero>('addHero'))
    )
  }
  deleteHero(hero:Hero|number):Observable<Hero>{
    console.log(hero)
    const id = typeof hero ==='number' ? hero:hero.id;
    const url =`${this.heroesUrl}/${id}`;
    console.log(url)
    return this.http.delete<Hero>(url,httpOptions)
    .pipe(
      tap(_=>this.log(`deleted hero w/ id=${id}`)),
      catchError(this.handleError<Hero>('deleteHero'))
    )
  }
  searchHeroes(term:string):Observable<Hero[]>{
    if(!term.trim()){
      return of([])
    }
    return this.http.get<Hero[]>(`${this.heroesUrl}/?name=${term}`).pipe(
      tap(_=>this.log(`found heroes match "${term}"`)),
      catchError(this.handleError<Hero[]>('searchHeroes',[]))
    )
  }
 
}
